package com.test.particles;

import java.util.Iterator;
import java.util.LinkedList;

import javax.vecmath.Point2f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector2f;

import android.content.Context;
import android.util.Log;

public class ParticleSystem {
	private static final String TAG = "ParticleSystem";
	
	public void step()
	{
		Log.i(TAG,"stepping");

        long currentTime = android.os.SystemClock.uptimeMillis();
        
        float timeDiff = currentTime - mLastTime;
        
        float dt = (float) timeDiff / 1000.0f;
               
        collideBorders(dt);
        
        Iterator<Particle> iterator = mParticles.iterator();
        
        while(iterator.hasNext())
        {
        	Particle currentParticle = iterator.next();
        	
//        	mLookupGrid.addParticle(currentParticle);
        	
        	float[] gvals = new float[3];
        	tiltcalc.getTilt(gvals);
        	Vector2f g = new Vector2f(gvals[2], gvals[1]);
        	//Point2f g = new Point2f(0.0f, -1.5f);
        	
//        	Point2f g = new Point2f (0.0f, -1.0f);
        	
        	currentParticle.addAccel(g);
        	
        	currentParticle.integrate(dt);
//        	currentParticle.integrateRK4(currentTime, dt);
        	
        	currentParticle.resetAccel();
        	
//        	if(currentParticle.getPos().y < 0.0f) {
//        		iterator.remove();
//        	}	
        }
        
        // reset iterator
        iterator = mParticles.iterator();
        
        while(iterator.hasNext())
        {
        	Particle currentParticle = iterator.next();
        	
        	Point3f color = new Point3f(1,1,1);
        	
        	int numInCell = mLookupGrid.getCellParticles(currentParticle.getCell()).size();
        	
        	if(numInCell > 1)
        	{
        		color.y = 0.0f;
        		color.z = 0.0f;
        	}
        	
        	currentParticle.setColor(color);        	
        }
        
        
        mLastTime = currentTime;
	}
	
	private void collideBorder(Particle particle, Point2f pos, Vector2f normal, float dt)
	{
		normal.normalize();
		
    	Vector2f relPos = new Vector2f();
    	
    	relPos.x = particle.getPos().x - pos.x;
    	relPos.y = particle.getPos().y - pos.y;
    	
    	float dist = relPos.dot(normal);
    	
    	float normalVel = particle.getVel().dot(normal);
    	
    	if(dist < 0.0f)
    	{
    		Vector2f normalForce = (Vector2f) normal.clone();
    		
    		float springConst = 1000.0f;
    		float damping = Math.min(10.0f, 1.0f/dt);
    		
    		normalForce.scale(-1.0f * springConst * dist + -1.0f * damping * normalVel);
    		
    		particle.addAccel(normalForce);
    		
//    		particle.setColor(new Point3f(1,0,0));
    	}	
	}
	
	private void collideBorders(float dt)
	{
        Iterator<Particle> iterator = mParticles.iterator();
        
        while(iterator.hasNext())
        {
        	Particle currentParticle = iterator.next();
        	
//        	currentParticle.setColor(new Point3f(1,1,1));
        	
        	collideBorder(currentParticle, new Point2f(0.0f,0.02f), new Vector2f(0.0f,1.0f), dt);
        	collideBorder(currentParticle, new Point2f(0.0f,mDimensions.y - 0.02f), new Vector2f(0.0f,-1.0f), dt);
        	collideBorder(currentParticle, new Point2f(1.0f - 0.02f,0.0f), new Vector2f(-1.0f,0.0f), dt);
        	collideBorder(currentParticle, new Point2f(0.02f,0.0f), new Vector2f(1.0f,0.0f), dt);
        }
	}
	
	ParticleSystem()
	{
		mCount = 0;
		mParticles = new LinkedList<Particle>();
		
		mLastTime = android.os.SystemClock.uptimeMillis();
	}
	
	public void setDimensions(Point2f dimensions)
	{
		mDimensions = dimensions;
		
		mLookupGrid = new UniformGrid(new Point2f(0.0f,0.0f), dimensions);
	}
	
	public void addParticle(float posX, float posY)
	{
		Particle p = new Particle(posX, posY);
		mParticles.addLast(p);
		
		mCount++;
	}
	
	public int getCount() {
		return mCount;
	}
	
	public TiltCalc tiltcalc;
	public void setTiltCalc(Context c)
	{
		tiltcalc = new TiltCalc(c);
	}
	
	public LinkedList<Particle> getParticles() {
		return mParticles;
	}
	
	private Point2f mDimensions;
	
	private int mCount;
    private LinkedList<Particle> mParticles;

	private long mLastTime;
	
	private UniformGrid mLookupGrid;
	
}
